Enable autovectorization on all compilers#3739
Conversation
|
As mentioned in #3662 my compiler seems to autovectorize already. I see |
|
I benchmarked this change on Linux to help move it forward. Summary: the claim in the PR description is correct — with the current Setup: g++ 13.3.0 (Ubuntu 24.04, x86-64), current 1. Compiler vectorization reports on the real
|
| Variant | Vectorized loops in the mix function |
|---|---|
-O2 (current) |
0 (only one trivial SLP basic-block) |
-O2 -ftree-vectorize (this PR) |
8 — all four mono-target mix loops, both stereo-target no-delay-pan mix loops, both Float2Short conversion loops |
-O3 |
same 8 loops |
So on GCC 13 nothing in the mixing path vectorizes today, and the PR's flag reaches exactly the same set of loops as -O3. (The delay-pan loops don't vectorize under any variant due to the wrap-around conditionals — pre-existing, unchanged.)
2. Microbenchmark of the mixing loops
Loop bodies lifted verbatim from MixEncodeTransmitData (CVector is std::vector, runtime trip count, same access pattern). Each measurement is one full target-channel frame: buffer reset + mix of N clients + Float2Short conversion; best of 30 runs × 20 000 reps. Times in ns per target-channel frame:
| Frame | Clients | Mode | -O2 |
-O2 -ftree-vectorize |
-O3 |
Speedup (PR vs -O2) |
|---|---|---|---|---|---|---|
| 64 | 10 | mono | 1091 | 285 | 260 | 3.8× |
| 64 | 10 | stereo | 1024 | 407 | 418 | 2.5× |
| 64 | 50 | mono | 3235 | 1104 | 978 | 2.9× |
| 64 | 50 | stereo | 4931 | 1986 | 1822 | 2.5× |
| 128 | 10 | mono | 1339 | 419 | 551 | 3.2× |
| 128 | 10 | stereo | 2642 | 1177 | 1183 | 2.2× |
| 128 | 50 | mono | 7873 | 2463 | 2659 | 3.2× |
| 128 | 50 | stereo | 14248 | 5232 | 5130 | 2.7× |
Whole-server impact scales with N² (each of N clients gets its own N-way mix). Example: 50 mono clients at the 128-sample frame size = 50 × 7.9 µs = ~394 µs of mixing per 2.67 ms frame period (≈15% of a core) at -O2, dropping to ~123 µs (≈4.6%) with this PR. Stereo: ≈27% → ≈10%.
3. Safety notes
- These loops vectorize over the sample index; each output sample keeps its exact scalar operation order (no FP reassociation —
-ftree-vectorizedoes not imply-ffast-math), so output is bit-identical, consistent with the "safe to default-enable" assessment. - The full autobuild matrix on this PR is green, including both Windows builds — MSVC ignores the unknown
-ftree-vectorizewith a warning, so the flag is inert (not harmful) there. If the warning noise bothers anyone it could be scoped to gcc/clang mkspecs, but it's not a correctness issue. - @dingodoppelt: on g++ 13, plain
-O2definitely does not enable loop vectorization (-ftree-vectorizeis only implied from-O3up) — if your local builds vectorize at-O2, something else in your flags is adding it. And per the table above,-O3buys nothing further for this code, so the PR's minimal flag seems like the right call.
Benchmark source available on request.
🤖 Generated with Claude Code
I think it would be worth putting a guard in the Additionally, it might be worth investigating what the equivalent in the MSVC builds looks like - in terms of performance now and potential for optimisation. This step isn't a blocker, though. |
|
I've added this to 4.0.0 as it's a small change with potentially wide-scale benefit right now. |
Short description of changes
Enables autovectorization throughout the whole codebase. We found out that there is no vectorization especially of the server side mixing code (#3662 (comment))
I consider this safe to default enable; in case of bugs we'd have a compiler bug.
CHANGELOG: Performance: Enable auto vectorization by default
Context: Fixes an issue?
Related to: #3662 (comment)
Does this change need documentation? What needs to be documented and how?
Status of this Pull Request
Ready for testing on all supported OS.
What is missing until this pull request can be merged?
Build with multiple compilers
Checklist
AUTOBUILD: Please build all targets